home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Telnet 2.6.1d1 / src / source / network / MacTCP / network.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-16  |  28.8 KB  |  1,178 lines  |  [TEXT/KAHL]

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1993,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. *****************************************************************
  13. *  Revisions:
  14. *  10/87  Initial source release, Tim Krauskopf
  15. *  2/88  typedef support for other compilers (TK)
  16. *  8/88  Gaige Paulsen - support for MacTCP drivers
  17. *  1/89  TK - conversion to new drivers, minor update for new calling convention
  18. *  6/89  TK - update to MacTCP 1.0 include files and use of GetMyIPAddr()
  19. *  7/92  Scott Bulmahn - add support for 2 global structs, put cursors into an array
  20. *  11/92 Jim Browne - Fixed more bugs than I care to mention.                    
  21. *
  22. */
  23.  
  24. #ifdef MPW
  25. #pragma segment Network
  26. #endif
  27.  
  28. #include "TelnetHeader.h"
  29. #include <TCPPB.h>
  30. #include <stdio.h>
  31. #include <String.h>
  32. #include "telneterrors.h"
  33. #include "InternalEvents.h"
  34. #include "maclook.proto.h"
  35. #include "menuseg.proto.h"
  36. #include "mainseg.proto.h"
  37. #include "getmyipaddr.h"    /* BYU LSC */
  38. #include "MyMacTCPstructures.h"
  39. #include "wind.h"
  40. #include "network.proto.h"
  41. #include "netevent.proto.h"
  42. #include "encrypt.proto.h"
  43. #include "DlogUtils.proto.h"    // For WriteZero
  44. #include "debug.h"
  45.  
  46. #ifdef THINK_C
  47. #pragma options(!profile)
  48. #endif
  49.  
  50. #ifdef __MWERKS__
  51. #pragma profile off
  52. #endif
  53.  
  54. //#define NET_DEBUG_MUCHINFO
  55. //#define    NET_DEBUG
  56. #ifdef    NET_DEBUG
  57. char    net_debug_string[256];
  58. #define    net_debug_print(x)    putln(net_debug_string)
  59. #else
  60. #define    net_debug_print(x)    
  61. #endif
  62.  
  63. pascal void Notify(StreamPtr streamPtr, unsigned short code, Ptr uptr, 
  64.                         unsigned short terminReason, struct ICMPReport *icmpMsg);
  65. PROTO_UPP(Notify, TCPNotify);
  66. static    TCPIOCompletionProc        OpenCompleteInit(TCPiopb *pbp);
  67. PROTO_UPP(OpenCompleteInit, TCPIOCompletion);
  68. static    TCPIOCompletionProc        CloseCompleteInit(TCPiopb *pbp);
  69. PROTO_UPP(CloseCompleteInit, TCPIOCompletion);
  70. static    TCPIOCompletionProc        SendCompleteInit(TCPiopb *pbp);
  71. PROTO_UPP(SendCompleteInit, TCPIOCompletion);
  72. static    void        OpenComplete(MyTCPpbPtr pbp);
  73. static    void        SendComplete(MyTCPpbPtr pbp);
  74. static    void        CloseComplete(MyTCPpbPtr pbp);
  75.  
  76. static    wdsEntry    *getSWDS(void);
  77. static    void        returnSWDS(wdsEntry *wds);
  78. static    void        MyPBreturn(MyTCPpbPtr pbp);
  79. static    MyTCPpb        *getPB(short driver,short call, StreamPtr stream, short usernum);
  80. static    void        clearPB(MyTCPpbPtr pbp, short driver, short call, StreamPtr stream);
  81. static    OSErr        xPBControlSync(MyTCPpbPtr pbp);
  82. static    OSErr        xPBControlAsync(MyTCPpbPtr pbp, TCPIOCompletionProc completion);
  83. static    short        makestream(void);
  84. static    void        reclaim(StreamRPtr p);
  85. static    short        giveback(StreamRPtr p, wdsEntry *wds);
  86. static    void        compressfds(wdsEntry *fds);
  87.  
  88. extern Cursor    *theCursors[];
  89. extern WindRec    *screens;
  90.  
  91. long        MyA5;
  92. short        TCPd = 0;                    /* refnum of TCP drivers */
  93. QHdr        gFreePBQueue;
  94. QHdr        gFreeSWDSQueue;
  95. short         numSWDS=0;                    /* Number of SWDS's ever alloc'd (PM Only) */
  96. StreamRPtr    streams[NPORTS];
  97. ip_port        nnfromport = 0;
  98.  
  99. /**************************************************************************/
  100. wdsEntry    *getSWDS(void)
  101. {
  102.     short        n=0;
  103.     wdsEntry *    wds;
  104.     
  105.     if (gFreeSWDSQueue.qHead == NULL)
  106.         wds = (wdsEntry *) NewPtrClear( sizeof(wdsEntry) * MAX_SWDS_ELEMS);    
  107.     else
  108.         {
  109.         wds = (wdsEntry *) gFreeSWDSQueue.qHead;
  110.         Dequeue(gFreeSWDSQueue.qHead, &gFreeSWDSQueue);
  111.         }
  112.         
  113.     if (wds == NULL) {    /* sorry, cant allocate WDS (BIG PROBLEM) */
  114.         DoError(508 | NET_ERRORCLASS, LEVEL3, NULL); // <- Is 508 correct?
  115.         forcequit();
  116.         // return ((wdsEntry*) 0L); <- ?? perhaps
  117.         }
  118.  
  119.     return(wds);
  120. }
  121.  
  122. /**************************************************************************/
  123. void    returnSWDS(wdsEntry *wds)
  124. {
  125.     Enqueue((QElemPtr)wds, &gFreeSWDSQueue);
  126. }
  127.  
  128. /**************************************************************************/
  129. void MyPBreturn(MyTCPpbPtr pbp)
  130. {
  131.     Enqueue((QElemPtr)pbp, &gFreePBQueue);
  132. }
  133.  
  134. /**************************************************************************/
  135. MyTCPpb *getPB(short driver,short call, StreamPtr stream, short usernum)
  136. {
  137.     #pragma unused (usernum)
  138.     MyTCPpb *pbp;
  139.  
  140.     if (gFreePBQueue.qHead == NULL)
  141.         pbp = (MyTCPpbPtr) NewPtrClear( sizeof(MyTCPpb) );
  142.     else
  143.         {
  144.         pbp = (MyTCPpbPtr) gFreePBQueue.qHead;
  145.         Dequeue(gFreePBQueue.qHead, &gFreePBQueue);
  146.         }
  147.         
  148.     if (pbp == NULL) {    /* sorry, cant allocate TCP buffer (BIG PROBLEM) */
  149.         DoError(508 | NET_ERRORCLASS, LEVEL3, NULL);
  150.         forcequit();
  151.         }
  152.     
  153.     memset((char *) pbp, '\0', sizeof(MyTCPpb));    
  154.     pbp->pb.ioCRefNum = driver;
  155.     pbp->pb.tcpStream = stream;
  156.     pbp->pb.csCode = call;
  157.     
  158.     return(pbp);
  159. }
  160.  
  161. /**************************************************************************/
  162. void clearPB(MyTCPpbPtr pbp, short driver, short call, StreamPtr stream)
  163. {
  164.     WriteZero((Ptr)pbp, sizeof(MyTCPpb));    /* BYU LSC - Default to all zeros */    
  165.     pbp->pb.ioCRefNum = driver;
  166.     pbp->pb.tcpStream = stream;
  167.     pbp->pb.csCode = call;
  168. }
  169.  
  170. /**************************************************************************/
  171. OSErr xPBControlSync(MyTCPpbPtr pbp) 
  172.     pbp->pb.ioCompletion = 0L;                         /* Charlie will puke if he ever sees */
  173.     return PBControl((ParmBlkPtr)(pbp),false);         /* his funtions here. -- JMB */
  174. }
  175.  
  176. /**************************************************************************/
  177. OSErr xPBControlAsync(MyTCPpbPtr pbp, TCPIOCompletionProc completion) 
  178. #ifndef __powerpc__
  179.     pbp->SavedA5 = MyA5;
  180. #endif
  181.     pbp->pb.ioCompletion = completion; 
  182.     return(PBControl((ParmBlkPtr)(pbp),true));        /* async */
  183. }
  184.  
  185. void    SetPortType(short port, short type)
  186. {
  187.     if (port >= 0 && port < NPORTS && (streams[port] != NULL))
  188.         streams[port]->portType = type;
  189. }
  190.  
  191. short    GetPortType(short port)
  192. {
  193.     if (port >= 0 && port < NPORTS && (streams[port] != NULL))
  194.         return(streams[port]->portType);
  195.     else return(-1);
  196. }
  197.  
  198. /**************************************************************************/
  199. /*    Returns an empty stream */ 
  200. short makestream(void)
  201. {
  202.     short        pnum, i;
  203.     StreamRPtr    p;
  204.     MyTCPpbPtr    pbp;
  205.  
  206.     for ( pnum=0; (streams[pnum]!= NULL) && pnum<NPORTS; pnum++);    /* BYU 2.4.16 */
  207.     
  208.     if (pnum >= NPORTS)
  209.         return(-2);
  210.  
  211.      if (!(p = streams[pnum] = (StreamRPtr) NewPtrClear(sizeof(StreamRec))))
  212.          return(-1);
  213.   
  214.      if ((p->buffer = (char *) NewPtrClear( TCPBUFSIZ)) == NULL) {
  215.          DisposePtr((Ptr)p);
  216.          streams[pnum] = 0;
  217.           return(-1);
  218.      }
  219.      if ((p->sbuffer = (char *) NewPtrClear( TCPBUFSIZ)) == NULL) {
  220.          DisposePtr((Ptr)p->buffer);
  221.          DisposePtr((Ptr)p);
  222.          streams[pnum] = 0;
  223.           return(-1);
  224.      }    
  225.  
  226.     
  227.     for (i=0; i<MAX_FDS_ELEMS; i++) 
  228.         {
  229.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  230.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  231.         }
  232.     p->fds[0].length = TCPBUFSIZ;
  233.     p->fds[0].ptr = p->sbuffer;
  234.     p->maxFDSused=0;
  235.     p->edata = NULL;
  236.     
  237.     pbp=getPB( TCPd, TCPCreate, (long) 0, 7);    /* BYU LSC important - Make create call */
  238.     pbp->pb.csParam.create.rcvBuff = p->buffer;
  239.     pbp->pb.csParam.create.rcvBuffLen = TCPBUFSIZ;
  240.     pbp->pb.csParam.create.notifyProc = (TCPNotifyProc)NotifyUPP;
  241.  
  242.     if (xPBControlSync(pbp) != noError) 
  243.         DoError (512 | NET_ERRORCLASS, LEVEL2, NULL);
  244.  
  245.     p->stream = pbp->pb.tcpStream;
  246.     
  247.     net_debug_print("Made new stream");
  248.     MyPBreturn(pbp);
  249.     return(pnum);
  250. }
  251.  
  252. /**************************************************************************/
  253. /*    reclaim( p) -
  254.         reclaims buffer space to stream (from pointer p) into the FDS list  */
  255.  
  256. void reclaim(StreamRPtr p)
  257. {
  258.     short n=0, offset=0;
  259.     
  260.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  261.     
  262.     if (offset >= MAX_FDS_ELEMS) /* offset too large -- cant reclaim */        
  263.         return;
  264.         
  265.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) 
  266.         {
  267.         if (p->exFDS[ n].inuse) 
  268.             {
  269.             p->fds[ offset++]=p->exFDS[ n].fds;
  270.             p->exFDS[ n].inuse = 0;
  271.             }
  272.         }
  273. }
  274.  
  275. /**************************************************************************
  276.     giveback( p, wds) - gives WDS entries back to the stream by putting them in the 
  277.          mutually exclusive buffer.
  278.     p -> stream
  279.     wds -> wds array            */
  280. short giveback(StreamRPtr p, wdsEntry *wds)
  281. {
  282.     short n=0, m=0;
  283.     
  284.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) 
  285.         {
  286.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  287.         if (m >= MAX_FDS_ELEMS)                                    // This was off by one - JMB 2.6
  288.             return(-1);                /* No room in the RECLAIMation center */
  289.         else 
  290.             {
  291.             p->exFDS[ m].inuse =1;
  292.             p->exFDS[ m].fds = wds[n];
  293.             m++;
  294.             }
  295.         n++;
  296.         }
  297. }
  298.  
  299. /**************************************************************************/
  300. /*    compressfds( fds)
  301.         compress an fds data structure to make everyone happy */
  302. void compressfds(wdsEntry *fds)
  303. {
  304.     short n,m,compressed;
  305.     
  306.     compressed = 0;
  307.     
  308.     while ( !compressed) {
  309.         compressed=1;
  310.         for (n=0; n< MAX_FDS_ELEMS; n++) 
  311.             {                /* Slow Forwards */
  312.             if (fds[n].ptr) 
  313.                 {                                /* Do if N exists */
  314.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) 
  315.                     {    /* Fast Backwards */
  316.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  317.                         fds[n].length+=fds[m].length;
  318.                         fds[n].ptr = fds[m].ptr;
  319.                         fds[m].ptr=0L;
  320.                         fds[m].length=0;
  321.                         compressed=0;
  322.                         }
  323. #ifdef CHECKBOTHWAYZ
  324.                     else 
  325.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) 
  326.                         {
  327.                         fds[m].length+=fds[n].length;
  328.                         fds[n].ptr=0L;
  329.                         fds[n].length=0;
  330.                         compressed=0;
  331.                         }
  332. #endif CHECKBOTHWAYZ
  333.                     }
  334.                 }
  335.             }
  336.         }
  337.     m=0;n=0;
  338.     
  339.     /* Close the gaps */
  340.     
  341.     while (n+m < MAX_FDS_ELEMS) 
  342.         {
  343.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS)
  344.             m++;            /* increase gap to valid entry */
  345.         if (n+m<MAX_FDS_ELEMS)
  346.             fds[n]=fds[n+m];
  347.         n++;
  348.         }
  349.     
  350.     /* Get rid of the empty spaces */
  351.     
  352.     n--;        /* for the next loop */
  353.     while (n < MAX_FDS_ELEMS)
  354.         {
  355.         fds[n].ptr=0;
  356.         fds[n++].length=0;
  357.         }
  358. }
  359.  
  360. /***************************************************************************/
  361. /*  Mnetread
  362. *   Read from a connection buffer into a user buffer.  
  363. *   Returns number of bytes read, < 0 on error
  364. * NOTE:
  365. *    current version very inefficient, but hopefully works.
  366. */
  367. short    netread(short pnum, void *buffer, short n)
  368. {
  369.     short        i;
  370.     StreamRPtr    p;
  371.     MyTCPpbPtr    pbp;
  372.     short        inQ, reqdamt;
  373.  
  374.     if (pnum < 0 || pnum >= NPORTS)            /* BYU 2.4.15 */
  375.         return(-2);
  376.  
  377.     if (NULL == (p = streams[pnum]))
  378.         return(-2);
  379.         
  380.     pbp=getPB( TCPd, TCPStatus, p->stream, 1);                /* Make status call */
  381.     if (xPBControlSync(pbp) != noError)                     /* status call bombed */
  382.         DoError (509 | NET_ERRORCLASS, LEVEL1, "Mnetread");
  383.  
  384.     if (pbp->pb.csParam.status.connectionState !=8) {
  385. #ifdef    NET_DEBUG
  386.         sprintf(net_debug_string, "CState: %d is %d",(int)pnum, (int)pbp->pb.csParam.status.connectionState);
  387.         net_debug_print(net_debug_string);
  388. #endif
  389.         MyPBreturn(pbp);
  390.         return(-1);                              /* Connection not established */
  391.         }
  392.     
  393.     inQ = pbp->pb.csParam.status.amtUnreadData;
  394.     reqdamt = n >inQ ? inQ : n;
  395.     
  396.     clearPB( pbp, TCPd, TCPRcv, p->stream);
  397.     pbp->pb.csParam.receive.rcvBuff = buffer;
  398.     pbp->pb.csParam.receive.rcvBuffLen = reqdamt;
  399.     
  400.     if (reqdamt<1) 
  401.         {                                /* Drop out if no data */
  402.         MyPBreturn(pbp);
  403.         return(0);
  404.         }
  405.     
  406.     if ((i = xPBControlSync(pbp)) != noError) {
  407.         DoError (524 | NET_ERRORCLASS, LEVEL1, NULL);
  408.         return(-1);
  409.         }
  410.         
  411.     reqdamt = pbp->pb.csParam.receive.rcvBuffLen;
  412.     if (reqdamt<inQ) 
  413.         netputuev( CONCLASS, CONDATA, pnum,0);            /* more data to get */
  414.  
  415.      /* Decrypt data */
  416.      if (p->edata && (((CDATA *)(p->edata))->decrypt_input)) {
  417.          unsigned char *cp = (unsigned char *)buffer;
  418.          short len = reqdamt;
  419.          
  420.          while (len-- > 0) {
  421.              *cp = (*((CDATA *)(p->edata))->decrypt_input)((CDATA *)p->edata, (int)(*cp));
  422.              cp++;
  423.          }        
  424.      }
  425.  
  426.     MyPBreturn(pbp);
  427.     return(reqdamt);
  428. }
  429.  
  430. /************************************************************************/
  431. /* netwrite
  432. *  write something into the output queue, netsleep routine will come
  433. *  around and send the data, etc.
  434. *
  435. */
  436. short    netwrite(short pnum, void *buffer, short nsend)
  437. {    
  438.     StreamRPtr    p;
  439.     wdsEntry    *swds;
  440.     short        remaining, queued, n,m;
  441.     MyTCPpbPtr    pbp;
  442.     OSErr        err;
  443.  
  444. #ifdef    NET_DEBUG_MUCHINFO
  445.     sprintf(net_debug_string, "port: %d\tbuffer: %lx\tnsend %d", pnum,
  446.         (unsigned int)buffer, (int)nsend);
  447.     net_debug_print(net_debug_string);
  448. #endif
  449.  
  450.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  451.         return(-2);
  452.  
  453.     if ( (p = streams[pnum]) == NULL)
  454.         return(-2);
  455.     
  456.     if ( !nsend )
  457.         return(0);
  458.  
  459.     swds = getSWDS();
  460.     
  461.     if (swds == NULL) return(nsend);        // Duh, Mr. Bulmahn. - JMB 2.6
  462.     
  463.     reclaim( p);
  464.  
  465.     compressfds( p->fds);
  466.  
  467.     n=0; remaining = nsend;
  468.  
  469. //    if (p->fds[0].ptr == 0) DebugStr("\pArgh! fds[0] is NULL!");
  470.     
  471.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  472. //        if (n >= MAX_SWDS_ELEMS) DebugStr("\pOverflowing SWDS in while loop!");
  473.         
  474.         swds[n].ptr = p->fds[n].ptr;
  475.         if ( p->fds[n].length > remaining) {
  476.             swds[n].length = remaining;
  477.             p->fds[n].length -= remaining;
  478.             p->fds[n].ptr += remaining;
  479.             remaining=0;
  480.             }
  481.         else 
  482.             {
  483.             swds[n].length =  p->fds[n].length;
  484.             remaining -= p->fds[n].length;
  485.             p->fds[n].length = 0;
  486.             p->fds[n].ptr = 0;
  487.             }
  488.         n++;
  489.         }
  490.  
  491.     if (n>p->maxFDSused) p->maxFDSused=n;
  492.     
  493.     compressfds( p->fds);
  494.  
  495.     queued = nsend-remaining;
  496.     
  497.     for(m=0; m<n; m++) {
  498. #ifdef    NET_DEBUG_MUCHINFO
  499.     sprintf(net_debug_string, "swds[m].ptr: %lx\tswds[m].length: %d", (unsigned int)swds[m].ptr, (int)swds[m].length);
  500.     net_debug_print(net_debug_string);
  501. #endif
  502.         }
  503.         
  504.     for (m=0; m<n; m++) 
  505.         {
  506.         BlockMove(buffer, swds[m].ptr, swds[m].length);    /* BYU LSC - Put data in WDS */
  507.     
  508.         /*
  509.          * encrypt if encrypting the session
  510.          */
  511.          if (p->edata && ((CDATA *)p->edata)->encrypt_output)
  512.              (*((CDATA *)p->edata)->encrypt_output)((CDATA *)p->edata, (unsigned char *)swds[m].ptr, swds[m].length);
  513.  
  514.         buffer=(void *)((char *)buffer + swds[m].length);
  515.         }
  516.     
  517.     swds[m].ptr = 0L;
  518.     swds[m].length=0;
  519.     
  520.     pbp=getPB( TCPd, TCPSend, p->stream, 2);            /* Make send call */
  521.     pbp->pb.csParam.send.wdsPtr = (Ptr) swds;
  522.     pbp->pb.csParam.send.pushFlag = p->push;
  523.     p->push=0;
  524.  
  525.     if ((err = xPBControlAsync(pbp, (TCPIOCompletionProc)SendCompleteInitUPP)) != noError) 
  526.         {
  527.         char temp_xvvyz[256];
  528.         
  529.         sprintf(temp_xvvyz, "netwrite: %d", err);
  530.         DoError(510 | NET_ERRORCLASS, LEVEL2, temp_xvvyz);
  531.         return(-1);
  532.         }
  533.  
  534.     return(queued);
  535. }
  536.  
  537. /**************************************************************************/
  538. /*  Mnetpush
  539. *   attempt to push the rest of the data from the queue
  540. *   and then return whether the queue is empty or not (0 = empty)
  541. *   returns the number of bytes in the queue.
  542. */
  543. short netpush(short pnum)
  544. {
  545.     StreamRPtr    p;
  546.     MyTCPpbPtr    pbp;
  547.     short        inQ;
  548.     OSErr        err;
  549.  
  550.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  551.         return(-2);
  552.  
  553.     if (NULL == (p = streams[pnum]))
  554.         return(-2);
  555.  
  556.     pbp=getPB( TCPd, TCPStatus, p->stream, 3);            /* Make status call */
  557. //#ifdef    NET_DEBUG_MUCHINFO
  558. //    sprintf(net_debug_string, "TCPd == %d", TCPd);
  559. //    net_debug_print(net_debug_string);
  560. //#endif
  561.     if ((err = xPBControlSync(pbp)) != noError) {        /* status call bombed */
  562.         char temp_xvvyz[256];
  563.  
  564.         sprintf(temp_xvvyz, "netpush: %d", err);
  565.         DoError(509 | NET_ERRORCLASS, LEVEL2, temp_xvvyz);
  566.         }
  567.         
  568.     inQ = pbp->pb.csParam.status.amtUnackedData;
  569.     MyPBreturn( pbp);
  570.     
  571.     p->push=1;
  572.     return(inQ);
  573. }    
  574.  
  575. /**************************************************************************/
  576. /*  Mnetqlen
  577. *   return the number of bytes waiting to be read from the incoming queue.
  578. */
  579. short netqlen(short pnum)
  580. {
  581.     StreamRPtr    p;
  582.     MyTCPpbPtr    pbp;
  583.     short        inQ;
  584.  
  585.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  586.         return(-2);
  587.  
  588.     if (NULL == (p = streams[pnum]))
  589.         return(-2);
  590.  
  591.     pbp=getPB( TCPd, TCPStatus, p->stream, 4);                /* Make status call */
  592.     if (xPBControlSync(pbp) != noError)                     /* status call failed */
  593.         DoError(509 | NET_ERRORCLASS, LEVEL2, "Mnetqlen");
  594.  
  595.     inQ = pbp->pb.csParam.status.amtUnreadData;
  596.     MyPBreturn( pbp);
  597.     
  598.     p->push = 1;
  599.     return(inQ);
  600. }
  601.  
  602. /**************************************************************************/
  603. /*  Mnetroom()
  604. *    return how much room is available in output buffer for a connection
  605. */
  606. short netroom(short pnum)
  607. {
  608.     StreamRPtr    p;
  609.     short        inQ, n;
  610.  
  611.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  612.         return(-2);
  613.  
  614.     if (NULL == (p = streams[pnum]))
  615.         return(-2);
  616.  
  617.     reclaim( p);
  618.     compressfds( p->fds);
  619.  
  620. #ifdef OLDM
  621.     pbp=getPB( TCPd, TCPStatus, p->stream, 5);            /* Make status call */
  622.     if (xPBControlSync(pbp) != noError) 
  623.         DoError(509 | NET_ERRORCLASS, LEVEL1, "Mnetroom");
  624.  
  625.     inQ = pbp->csParam.status.sendWindow -
  626.                 pbp->csParam.status.amtUnackedData;
  627.     MyPBreturn( pbp);
  628. #else
  629. /*#pragma unused(pbp)    /* BYU LSC */
  630. #endif
  631.  
  632.     inQ = n = 0;
  633.     while (p->fds[n].ptr) {
  634.     
  635.         inQ += p->fds[n].length;                /* add up free list space */
  636.         n++;
  637.         }
  638.  
  639.     return(inQ);
  640. }
  641.  
  642. /**************************************************************************/
  643. void netgetip(unsigned char *st)
  644. {
  645.     struct GetAddrParamBlock mypb;
  646.     /* long netmask; */
  647.  
  648.     net_debug_print("Attempting getmyipaddr");
  649.     
  650.     WriteZero((Ptr)&mypb, sizeof(struct GetAddrParamBlock));
  651.     
  652.     mypb.ioCRefNum = TCPd;            /* BYU LSC - TCP driver has to be open by now */
  653.     mypb.csCode = ipctlGetAddr;
  654.  
  655.     if (PBControl((ParmBlkPtr)&mypb, false) != noError) 
  656.         {
  657.         DoError(511 | NET_ERRORCLASS, LEVEL2, NULL);
  658.         return;
  659.         }
  660.     
  661.     BlockMove(&mypb.ourAddress, st, 4);    /* BYU LSC - copy the address */
  662.     /* netmask is here if we want it, too */
  663. }
  664.  
  665. void netfromport            /* next "open" will use this port */
  666.   ( short port)
  667. {
  668.     nnfromport = (ip_port)port;
  669. }
  670.  
  671. /**************************************************************************/
  672. /*  Mnetest?
  673. *  is a particular session established yet?
  674. *  Returns 0 if the connection is in the established state.
  675. */
  676. short netest(short pnum)
  677. {
  678.     StreamRPtr    p;
  679.     MyTCPpbPtr    pbp;
  680.     short        inQ;
  681.  
  682.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  683.         return(-2);
  684.  
  685.     if (NULL == (p = streams[pnum]))
  686.         return(-2);
  687.  
  688.     pbp=getPB( TCPd, TCPStatus, p->stream, 6);            /* Make status call */
  689.     if (xPBControlSync(pbp) != noError)
  690.         {
  691.         DoError(509 | NET_ERRORCLASS, LEVEL2, "Mnetest");
  692.         inQ = -1;
  693.         }
  694.     else 
  695.         inQ = pbp->pb.csParam.status.connectionState !=8;
  696.     MyPBreturn( pbp);
  697.     
  698.     return(inQ);
  699. }
  700.  
  701. /**************************************************************************/
  702. /*  Mnetlisten
  703. *   Listen to a TCP port number and make the connection automatically when
  704. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  705. *   with a CONOPEN event.  Save the port number returned to refer to this
  706. *   connection.
  707. *
  708. *   usage:   portnum = netlisten(service);
  709. *            short service;
  710. *
  711. */
  712.  
  713. short netlisten(ip_port serv)
  714. {
  715.     short        pnum;
  716.     StreamRPtr    p;
  717.     MyTCPpbPtr    pbp;
  718.  
  719.     pnum = makestream();
  720.  
  721.     if (pnum < 0 || pnum >= NPORTS)        /* BYU 2.4.15 */
  722.         return(-2);
  723.  
  724.     if (NULL == (p = streams[pnum]))
  725.         return(-2);
  726.  
  727.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, 8);            /* Make Listen call */
  728.     
  729.     pbp->pb.csParam.open.localPort = serv;
  730.     
  731.     if (xPBControlAsync(pbp, (TCPIOCompletionProc)OpenCompleteInitUPP) != noError) 
  732.         DoError(513 | NET_ERRORCLASS, LEVEL2, NULL);
  733.  
  734.     return(pnum);                        /* BYU 2.4.16 */
  735. }
  736.  
  737. /***********************************************************************/
  738. /*  Mnetgetftp
  739. *  Provides the information that ftp needs to open a stream back to the
  740. *  originator of the command connection.  The other side's IP number
  741. *  and the port numbers to be used to calculate the default data connection
  742. *  number.  Returns values in an integer array for convenient use in 
  743. *  PORT commands.
  744. */
  745. short    netgetftp(short pnum, ip_addr *addr, ip_port *localPort, ip_port *remotePort)
  746. {
  747.     StreamRPtr p;
  748.     MyTCPpbPtr pbp;
  749.     
  750.     if (pnum < 0)
  751.         return(-2);
  752.  
  753.     if (NULL == (p = streams[pnum]))
  754.         return(-2);
  755.  
  756.     pbp=getPB( TCPd, TCPStatus, p->stream, 9);            /* Make status call */
  757.     if (xPBControlSync(pbp) != noError) 
  758.         DoError(514 | NET_ERRORCLASS, LEVEL2, NULL);
  759.  
  760.     *addr = pbp->pb.csParam.status.remoteHost;
  761.     *localPort = pbp->pb.csParam.status.localPort;
  762.     *remotePort = pbp->pb.csParam.status.remotePort;
  763.     MyPBreturn( pbp);
  764. }
  765.  
  766. /**************************************************************************/
  767. /*  Open a network socket for the user. */
  768. short netxopen( ip_addr machine, ip_port service,
  769.                 short    timeout    )        // in seconds
  770. {
  771.     short        pnum;
  772.     StreamRPtr    p;
  773.     MyTCPpbPtr    pbp;
  774.  
  775.     pnum = makestream();
  776.  
  777.     if (pnum < 0)
  778.         return(-2);
  779.  
  780.     if (NULL == (p = streams[pnum]))
  781.         return(-2);
  782.  
  783.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, 10);            /* Make Listen call */
  784.     
  785.     pbp->pb.csParam.open.remoteHost = machine;            /* IP # */
  786.     pbp->pb.csParam.open.remotePort = service;                /* Port */
  787.     pbp->pb.csParam.open.localPort = nnfromport;            /* My Port */
  788.     pbp->pb.csParam.open.ulpTimeoutValue = (byte)timeout;    // timeout value
  789.     pbp->pb.csParam.open.ulpTimeoutAction = 1;                // Abort
  790.     pbp->pb.csParam.open.validityFlags = 0xC0;                // Timeout and action are valid
  791.     nnfromport=0;                                            /* Next one is random */
  792.     
  793.     if (xPBControlAsync(pbp, (TCPIOCompletionProc)OpenCompleteInitUPP) != noError) {
  794.         DoError(515 | NET_ERRORCLASS, LEVEL2, NULL);
  795.         return(-1);
  796.         }
  797.     
  798.     SetPortType(pnum, NO_TYPE);                // Is allocated to the user
  799.     
  800. #ifdef    NET_DEBUG
  801.     sprintf(net_debug_string, "TCPOpen on port #%d", pnum);
  802.     net_debug_print(net_debug_string);
  803. #endif
  804.     return(pnum);                    /* BYU 2.4.16 */
  805. }
  806.  
  807.  
  808. /**************************************************************************/
  809. /* Mnetclose
  810. *  Do appropriate actions to return connection state to SCLOSED which
  811. *  enables the memory for that port to be reused.
  812. *
  813. *    Specifically:
  814. *        o If status is closed, then release the data structures
  815. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  816. *            which should make the session layer call us again
  817. */
  818. short netclose(short pnum)
  819. {
  820.     StreamRPtr    p;
  821.     MyTCPpbPtr    pbp;
  822.     OSErr        errorCode;
  823.     short        status;
  824.     static        short count=0;
  825.  
  826.     errorCode = 0;
  827.     
  828.     if (pnum < 0 || pnum >= NPORTS)            /* is a valid port? */
  829.         return(-1);
  830.  
  831.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  832.         return (1);
  833.  
  834.     pbp=getPB( TCPd, TCPStatus, p->stream, 11);            /* Make status call */
  835.     if ((errorCode = xPBControlSync(pbp)) != noError) 
  836.         {
  837.         if ( errorCode == invalidStreamPtr)
  838.             {
  839.             DoError (516 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  840.             return(-1);
  841.             }
  842.         else
  843.             {
  844.             status=0;
  845.             count =0;
  846.             }
  847.         }
  848.     else 
  849.         {
  850.         status = pbp->pb.csParam.status.connectionState;            /* The connection Status */
  851.         if (count++ ==10) 
  852.             {
  853.             status= 0;
  854.             count =0;
  855.             }
  856.         }
  857.  
  858. /* */
  859.  
  860. #ifdef    NET_DEBUG
  861.     sprintf(net_debug_string, "Mnetclose:error code=%i status=%d",(int)errorCode, status);
  862.     net_debug_print(net_debug_string);
  863. #endif
  864.  
  865.     if (status < 18 && status >2 ) {    /* We aren't closed yet ! */
  866. #ifdef    NET_DEBUG
  867.         sprintf(net_debug_string, "TCPClose being attempted state ...[%d]",status); /* Prolly because outstanding close */
  868.         net_debug_print(net_debug_string);
  869. #endif
  870.         clearPB( pbp, TCPd, TCPClose, p->stream);            /* Make Close call */
  871.         if ((errorCode=xPBControlAsync(pbp, (TCPIOCompletionProc)CloseCompleteInitUPP)) != noError) 
  872.             {            /* TCP close failed */
  873.             DoError(517 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  874.             return (errorCode);
  875.             }
  876.  
  877.         /* Go ahead and return... PB is in use by Async Close call. */
  878.         return (0);                                            /* Return with OK */
  879.         }
  880.  
  881.     /* IF we got here, we must be at closed state, so free memory */
  882.  
  883. #ifdef    NET_DEBUG
  884.     sprintf(net_debug_string, "TCP being released, status = %d", status);
  885.     net_debug_print(net_debug_string);
  886. #endif
  887.  
  888.     clearPB( pbp,TCPd, TCPRelease, p->stream);            /* Make Release call */
  889.     if (xPBControlSync(pbp) != noError) 
  890.         {                /* TCP failed to be released.  Let us know... */
  891.         DoError (518 | NET_ERRORCLASS, LEVEL2, "Mnetclose");
  892.         return (-1);
  893.         }
  894.     
  895.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  896.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  897.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  898.     streams[pnum]=0L;
  899.     netportencryptstate(pnum, 0);
  900.  
  901.     MyPBreturn(pbp);
  902.     return(0);
  903. }
  904.  
  905. /**************************************************************************/
  906. /*    Nuke the connection, NOW! */
  907. short    netabort(short pnum)
  908. {
  909.     StreamRPtr    p;
  910.     MyTCPpbPtr    pbp;
  911.     OSErr        errorCode = noErr;
  912.  
  913.     if (pnum < 0 || pnum >= NPORTS)            /* is a valid port? */
  914.         return(-1);
  915.  
  916.     if ((p = streams[pnum]) != NULL)     /* something there */
  917.         {            
  918.         pbp=getPB( TCPd, TCPAbort, p->stream, 12);            /* Make Close call */
  919.         if ((errorCode=xPBControlSync(pbp)) != noError)         /* TCP abort failed.  Bad news */
  920.             DoError (519 | NET_ERRORCLASS, LEVEL1, NULL);
  921.         clearPB( pbp,TCPd, TCPRelease, p->stream);            /* Make Close call */
  922.         if (xPBControlSync(pbp) != noError) 
  923.             {
  924.             DoError (518 | NET_ERRORCLASS, LEVEL2, NULL);
  925.             return(-1);
  926.             }
  927.         }
  928.     else
  929.         return(1);
  930.     
  931.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  932.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  933.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  934.     streams[pnum]=0L;
  935.  
  936.     MyPBreturn(pbp);
  937.     return(0);
  938. }
  939.  
  940.  
  941. /**************************************************************************/
  942. /*  Mnetinit
  943. *   Calls all of the various initialization routines that set up queueing
  944. *   variables, static values, reads configuration files, etc.
  945. */
  946.  
  947. void Mnetinit( void)
  948. {
  949.     short    i;
  950.     OSErr    err;
  951.  
  952. #ifndef __powerpc__    
  953.     MyA5 = SetCurrentA5();
  954. #endif
  955.     
  956.     for (i=0; i<NPORTS;i++) {
  957.         streams[i]= (StreamRPtr) 0;
  958.         SetPortType(i, NO_TYPE);
  959.         } 
  960.         
  961.     gFreePBQueue.qHead = NULL;
  962.     gFreePBQueue.qTail = NULL;
  963.     gFreePBQueue.qFlags = 0;
  964.     gFreeSWDSQueue.qHead = NULL;
  965.     gFreeSWDSQueue.qTail = NULL;
  966.     gFreeSWDSQueue.qFlags = 0;
  967.         
  968.     if ((err = OpenDriver("\p.IPP",&TCPd)) != noError)         /* cant open the IP driver */
  969.         {    
  970.         SetCursor(theCursors[normcurs]);
  971.         FatalAlert(CANT_OPEN_MACTCP, 300, err);        // Doesn't return!
  972.         }
  973. }
  974.  
  975.  
  976.  
  977. /*************************************************************************/
  978. /*  Mnetshut
  979. *   Close all the connections and turn off the hardware.
  980. */
  981. void netshut(void)
  982. {
  983.     short    i;
  984.  
  985.     for (i=0; i < NPORTS ; i++) 
  986.         if (streams[i] != (StreamRPtr) NULL)
  987.             netabort(i);                        /* Prolly should abort */
  988. }
  989.  
  990. /**************************************************************************/
  991. short    findbystream(StreamPtr streamPtr)
  992. {
  993.     short    pnum=0;
  994.     
  995.     while (pnum<NPORTS &&
  996.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  997.         pnum++;
  998.     if (pnum >=NPORTS)
  999.         return(-1);
  1000.     else
  1001.         return(pnum);
  1002. }
  1003.  
  1004.  
  1005. /**************************************************************************/
  1006. SIMPLE_UPP(Notify, TCPNotify);
  1007. pascal void Notify(StreamPtr streamPtr, unsigned short code, Ptr uptr, 
  1008.                         unsigned short terminReason, struct ICMPReport *icmpMsg)
  1009. {
  1010.     #pragma unused(uptr, terminReason, icmpMsg)
  1011.     StreamRPtr    p;
  1012.     short        pnum;
  1013.     
  1014.     pnum = findbystream(streamPtr);
  1015.     
  1016.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1017.         return;
  1018.     
  1019.     switch( code) {
  1020.         case TCPTerminate:
  1021.         case TCPClosing:
  1022.             netputevent(CONCLASS, CONCLOSE, pnum,0);
  1023.             break;
  1024.         case TCPULPTimeout:
  1025.             netputevent(CONCLASS, CONFAIL, pnum,0);
  1026.             break;
  1027.         case TCPDataArrival:
  1028.         case TCPUrgent:
  1029.             netputuev(CONCLASS, CONDATA, pnum,0);
  1030.             break;
  1031.         case TCPICMPReceived:
  1032.         default:
  1033.             break;
  1034.         }
  1035.     return;
  1036. }
  1037.  
  1038. /**************************************************************************/
  1039. SIMPLE_UPP(OpenCompleteInit, TCPIOCompletion);
  1040. TCPIOCompletionProc OpenCompleteInit(TCPiopb *pbp)
  1041. {
  1042.     long        saveA5;
  1043.     MyTCPpbPtr    myptr;
  1044.     
  1045.     myptr = (MyTCPpbPtr)pbp;
  1046.  
  1047. #ifndef _powerpc_
  1048.     saveA5 = SetA5(myptr->SavedA5);
  1049. #endif
  1050.  
  1051.     OpenComplete(myptr);
  1052.  
  1053. #ifndef _powerpc_
  1054.     SetA5(saveA5);
  1055. #endif
  1056. }
  1057.  
  1058. /**************************************************************************/
  1059. void    OpenComplete(MyTCPpbPtr pbp)
  1060. {
  1061.     StreamRPtr    p;
  1062.     short        pnum;
  1063.  
  1064.     pnum= findbystream(pbp->pb.tcpStream);
  1065.     
  1066.     if (pnum < 0 || (p = streams[pnum]) == 0L) 
  1067.         MyPBreturn(pbp);
  1068.         
  1069.     if (pbp->pb.ioResult !=noError) 
  1070.         netputevent(CONCLASS, CONFAIL, pnum,0);            /* Failure ... */
  1071.     else 
  1072.         netputevent(CONCLASS, CONOPEN, pnum,0);            /* Success ! */
  1073.  
  1074.     MyPBreturn( pbp);
  1075. }
  1076.  
  1077. /**************************************************************************/
  1078. void    SendComplete(MyTCPpbPtr pbp)
  1079. {
  1080.     StreamRPtr    p;
  1081.     short        pnum;
  1082.     wdsEntry    *swds;
  1083.  
  1084.     swds = (wdsEntry *) pbp->pb.csParam.send.wdsPtr;
  1085.     
  1086.     pnum = findbystream(pbp->pb.tcpStream);
  1087.     
  1088.     if (pnum < 0 || (p = streams[pnum]) == 0L) {
  1089.         MyPBreturn(pbp);
  1090.         return;
  1091.         }
  1092.         
  1093.     MyPBreturn( pbp);
  1094.     giveback( p, (wdsEntry *) pbp->pb.csParam.send.wdsPtr);    /* BYU LSC - Give this back.... NOW */
  1095.     returnSWDS( swds);
  1096. }
  1097.  
  1098.  
  1099. /**************************************************************************/
  1100. SIMPLE_UPP(SendCompleteInit, TCPIOCompletion);
  1101. TCPIOCompletionProc SendCompleteInit(TCPiopb *pbp)
  1102. {
  1103.     long        saveA5;
  1104.     MyTCPpbPtr    myptr;
  1105.     
  1106.     myptr = (MyTCPpbPtr)pbp;
  1107.  
  1108. #ifndef _powerpc_
  1109.     saveA5 = SetA5(myptr->SavedA5);
  1110. #endif
  1111.     
  1112.     SendComplete(myptr);
  1113.     
  1114. #ifndef _powerpc_
  1115.     SetA5(saveA5);
  1116. #endif
  1117. }
  1118.  
  1119. /**************************************************************************/
  1120. void    CloseComplete(MyTCPpbPtr pbp)
  1121. {
  1122.     StreamRPtr    p;
  1123.     short        pnum;
  1124.  
  1125.     pnum= findbystream(pbp->pb.tcpStream);
  1126.     
  1127.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1128.       {
  1129.         netputevent(SCLASS, CLOSEDONE+1, pnum,0);
  1130.         MyPBreturn(pbp);
  1131.         return;
  1132.       }
  1133.         
  1134.     if (pbp->pb.ioResult !=noError) 
  1135.         netputevent(SCLASS, CLOSEDONE+1, pnum,0);
  1136.     else 
  1137.         netputevent(SCLASS, CLOSEDONE, pnum,0);            /* Success ! */
  1138.  
  1139.     MyPBreturn( pbp);
  1140. }
  1141.  
  1142. /**************************************************************************/
  1143. SIMPLE_UPP(CloseCompleteInit, TCPIOCompletion);
  1144. TCPIOCompletionProc CloseCompleteInit(TCPiopb *pbp)
  1145. {
  1146.     long        saveA5;
  1147.     MyTCPpbPtr    myptr;
  1148.     
  1149.     myptr = (MyTCPpbPtr)pbp;
  1150.  
  1151. #ifndef _powerpc_
  1152.     saveA5 = SetA5(myptr->SavedA5);
  1153. #endif
  1154.     
  1155.     CloseComplete(myptr);
  1156.     
  1157. #ifndef _powerpc_
  1158.     SetA5(saveA5);
  1159. #endif
  1160. }
  1161.  
  1162. short netportencryptstate (short port, Ptr edata)
  1163. {
  1164.     StreamRPtr    p;
  1165.  
  1166.     if (port < 0 || port >= NPORTS)
  1167.          return(-2);
  1168.  
  1169.      if ((p = streams[port]) == NULL)
  1170.          return(-2);
  1171.  
  1172.      p->edata = edata;
  1173.  
  1174.      return 0;
  1175. }
  1176.